﻿using Entity.CheckInEntity;
using Entity.ResultModel.Appoinement;
using IHotelBLL.ICheckInBLL;
using IHotelDAL;
using IHotelDAL.ICheckInDAL;
using IHotelDAL.IFrondeskDAL;
using IHotelDAL.IRoomDAL;
using Microsoft.EntityFrameworkCore.Storage;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HotelBLL.CheckInBLL
{
    public class AppointmentBLL : IAppointmentBLL
    {
        IAppointmentDAL _appointmentDAL;
        IRoomInfoDAL _roomInfoDAL;
        ICheckInDAL _checkInDAL;
        IFrontDeskDAL _frontDeskDAL;
        IUserInfoDAL _userInfoDAL;
        IRoomTypeDAL _roomTypeDAL;
        public AppointmentBLL(IAppointmentDAL appointmentDAL, IRoomInfoDAL roomInfoDAL, ICheckInDAL checkInDAL, IFrontDeskDAL frontDeskDAL, IUserInfoDAL userInfoDAL,IRoomTypeDAL roomTypeDAL)
        {
            _appointmentDAL = appointmentDAL;
            _roomInfoDAL = roomInfoDAL;
            _checkInDAL = checkInDAL;
            _frontDeskDAL = frontDeskDAL;
            _userInfoDAL = userInfoDAL;
            _roomTypeDAL = roomTypeDAL;
        }
        /// <summary>
        ///  客户预约，添加预约记录
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="checkInDate"></param>
        /// <param name="checkInDay"></param>
        /// <param name="creator"></param>
        /// <param name="roomId"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool AddAppointmentRecord(string userId, DateTime CheckInDate, string typeId, out string msg)
        {
            var room = _roomInfoDAL.GetEntities().Where(r => r.TypeId == typeId && r.Status == Entity.Enum.RoomStatusEnum.可入住).FirstOrDefault();
            var userInfo = _userInfoDAL.GetEntities().Where(u => u.Id == userId);
            if (userInfo is null)
            {
                msg = "未找到用户";
                return false;
            };
            if(room == null)
            {
                msg = "当前没有空余的房间";
                return false;
            }
            Appointment appointment = new Appointment()
            {
                Id = Guid.NewGuid().ToString(),
                CheckInDate = CheckInDate,
                Status = Entity.Enum.AppointmentStatusEnum.客户已预约,
                Amount = room.Price,
                CheckInDay = 1,
                CheckOutDate = CheckInDate.AddDays(1),
                RoomId = room.Id,
                UserId = userId,
            };
            bool isSuccess = _appointmentDAL.CreateEntity(appointment);

            msg = isSuccess ? "预约成功" : "预约失败";
            return false;
        }
        /// <summary>
        /// 酒店接受预约
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="appointmentId"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool HotelAcceeAppointment(string userId,string appointmentId, out string msg)
        {
            var appointment = _appointmentDAL.GetEntities().Where(a => a.Id == appointmentId).FirstOrDefault();
            var checkIn = _checkInDAL.GetEntities().Where(c => c.RoomId == appointment.RoomId).FirstOrDefault();
            if (appointment == null)
            {
                msg = "未找到预约订单信息";
                return false;
            }
            if (appointment.Status == Entity.Enum.AppointmentStatusEnum.客户已取消)
            {
                msg = "客户已取消订单";
                return false;
            }
            //判断前一个顾客是否退房
            if (!(checkIn is null))
            {
                msg = "已有客户入住";
                return false;
            }
            bool isSuccess = false;
            using (var transation = transaction())
            {
                try
                {
                    var room = _roomInfoDAL.GetEntities().Where(r => r.Id == appointment.RoomId).FirstOrDefault();
                    appointment.Status = Entity.Enum.AppointmentStatusEnum.酒店已接受;
                    room.Status = Entity.Enum.RoomStatusEnum.已预约;
                    appointment.Creator = userId;
                    bool Accept = _appointmentDAL.UpdateEntity(appointment);
                    bool ChangeRoomStatus = _roomInfoDAL.UpdateEntity(room);
                    if (Accept && ChangeRoomStatus)
                    {
                        transation.Commit();
                        isSuccess = true;
                    }
                    else
                    {
                        isSuccess = false;
                        transation.Rollback();
                    }
                }
                catch (Exception)
                {
                    msg = "程序出现异常,请联系管理员";
                    transation.Rollback();
                    return false;
                }
            }
            msg = isSuccess ? "已接受预约" : "无法接受预约";
            return isSuccess;
        }
        /// <summary>
        /// 顾客取消预约
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="appointmentId"></param>
        /// <returns></returns>
        public bool CustomerCancelAppointment(string userId, string appointmentId, string reason, out string msg)
        {
            var appointment = _appointmentDAL.GetEntities().Where(a => a.UserId == userId && a.Id == appointmentId).FirstOrDefault();
            if (appointment == null)
            {
                msg = "未找到预约订单信息，请确认是本人登录";
                return false;
            }
            appointment.Status = Entity.Enum.AppointmentStatusEnum.客户已取消;
            appointment.Reason = reason;
            bool isSuccess = _appointmentDAL.UpdateEntity(appointment);
            msg = isSuccess ? "取消成功" : "取消失败";
            return isSuccess;
        }
        /// <summary>
        /// 酒店取消订单
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="appointmentId"></param>
        /// <param name="reaseon"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool HotelCancelAppointment(string userId, string appointmentId, string reaseon, out string msg)
        {
            var appointment = _appointmentDAL.GetEntities().Where(a => a.Id == appointmentId).FirstOrDefault();
            if (appointment == null)
            {
                msg = "未找到订单信息";
                return false;
            }
            if (appointment.Status == Entity.Enum.AppointmentStatusEnum.客户已取消 || appointment.Status == Entity.Enum.AppointmentStatusEnum.酒店已取消)
            {
                msg = "该订单已取消";
                return false;
            }
            appointment.Status = Entity.Enum.AppointmentStatusEnum.酒店已取消;
            appointment.Reason = reaseon;
            appointment.Creator = userId;
            bool isSuccess = _appointmentDAL.UpdateEntity(appointment);
            msg = isSuccess ? "取消成功" : "取消失败";
            return isSuccess;
        }
        public List<GetAppoinements> GetAppointments(int page, int limit, out int count)
        {
            var datas = (from a1 in _appointmentDAL.GetEntities()
                         join r2 in _roomInfoDAL.GetEntities()
                         on a1.RoomId equals r2.Id
                         join f3 in _frontDeskDAL.GetEntities()
                         on a1.Creator equals f3.Id into actemp
                         from ac1 in actemp.DefaultIfEmpty()
                         join c1 in _userInfoDAL.GetEntities()
                         on a1.UserId equals c1.Id
                         select new GetAppoinements
                         {
                             AppointmentId = a1.Id,
                             CheckInDate = a1.CheckInDate.ToString("yyyy年MM月dd日"),
                             AppointmentStatus = a1.Status.ToString(),
                             RoomName = r2.Name,
                             EmployeeName = ac1.EmployeeName,
                             UserName = c1.Name,
                             Reason = a1.Reason
                         }).Where(c => c.AppointmentId != null).ToList();
            count = datas.Count();
            return datas;
        } public List<GetAppoinements> GetAppointmentOrders(int page, int limit, out int count)
        {
            var datas = (from a1 in _appointmentDAL.GetEntities()
                         join r2 in _roomInfoDAL.GetEntities()
                         on a1.RoomId equals r2.Id into artemp
                         from c1 in artemp.DefaultIfEmpty()
                         join f3 in _frontDeskDAL.GetEntities()
                         on a1.Creator equals f3.Id into actemp
                         from ac1 in actemp.DefaultIfEmpty()
                         join c2 in _userInfoDAL.GetEntities()
                         on a1.UserId equals c2.Id
                         where a1.Status == Entity.Enum.AppointmentStatusEnum.酒店已接受
                         select new GetAppoinements
                         {
                             AppointmentId = a1.Id,
                             CheckInDate = a1.CheckInDate.ToString("yyyy年MM月dd日"),
                             AppointmentStatus = a1.Status.ToString(),
                             RoomName = c1.Name,
                             EmployeeName = ac1.EmployeeName,
                             UserName = c2.Name,
                             Reason = a1.Reason
                         }).Where(c => c.AppointmentId != null);
            count = datas.Count();
            return datas.ToList();
        }
        public List<GetAppointment>  GetAppointment(string userId)
        {
            return (from a1 in _appointmentDAL.GetEntities()
                       join r1 in _roomInfoDAL.GetEntities()
                       on a1.RoomId equals r1.Id
                       where a1.UserId == userId
                       select new GetAppointment
                       {
                           CheckDay = a1.CheckInDay,
                           CheckInDate = a1.CheckInDate.ToString("yyyy-MM-dd"),
                           RoomType = r1.Name,
                           AppointmentStatus = a1.Status.ToString()
                       }).ToList();
        }
        public IDbContextTransaction transaction()
        {
            return _appointmentDAL.GetContext().Database.BeginTransaction();
        }
    }
}
